package com.marketlive.system.trace.log;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/*
(C) Copyright MarketLive. 2006. All rights reserved.
MarketLive is a trademark of MarketLive, Inc.
Warning: This computer program is protected by copyright law and international treaties.
Unauthorized reproduction or distribution of this program, or any portion of it, may result
in severe civil and criminal penalties, and will be prosecuted to the maximum extent
possible under the law.
*/


import java.io.Writer;
import java.io.IOException;
import java.io.StringWriter;

/**
 * Writes to a StringWriter that is bound to the current thread via a thread
 * local variable.  If no StringBuffer is defined for the thread the write call
 * is ignored.
 */
public class ThreadLocalBufferWriter extends Writer {

    private static ThreadLocal threadWriter = new ThreadLocal();

    /**
     * Logger
     */
    private static Log log = LogFactory.getLog(ThreadLocalBufferWriter.class);

    /**
     * Close the stream, flushing it first.  Once a stream has been closed,
     * further write() or flush() invocations will cause an IOException to be
     * thrown.  Closing a previously-closed stream, however, has no effect.
     *
     * @throws java.io.IOException If an I/O error occurs
     */
    public void close() throws IOException {
        StringWriter writer = (StringWriter) threadWriter.get();
        if (writer!=null) {
            writer.close();
        }
    }

    /**
     * Flush the stream.  If the stream has saved any characters from the
     * various write() methods in a buffer, write them immediately to their
     * intended destination.  Then, if that destination is another character or
     * byte stream, flush it.  Thus one flush() invocation will flush all the
     * buffers in a chain of Writers and OutputStreams.
     * <p/>
     * If the intended destination of this stream is an abstraction provided by
     * the underlying operating system, for example a file, then flushing the
     * stream guarantees only that bytes previously written to the stream are
     * passed to the operating system for writing; it does not guarantee that
     * they are actually written to a physical device such as a disk drive.
     *
     * @throws java.io.IOException If an I/O error occurs
     */
    public void flush() throws IOException {
        StringWriter writer = (StringWriter) threadWriter.get();
        if (writer != null) {
            writer.flush();
        }
    }

    /**
     * Write a portion of an array of characters.
     *
     * @param cbuf Array of characters
     * @param off  Offset from which to start writing characters
     * @param len  Number of characters to write
     * @throws java.io.IOException If an I/O error occurs
     */
    public void write(char cbuf[], int off, int len) throws IOException {
        StringWriter writer = (StringWriter) threadWriter.get();
        if (writer != null) {
            writer.write(cbuf,off,len);
        }
    }

    public String getBufferString() {
        StringWriter writer = (StringWriter) threadWriter.get();
        if (writer != null) {
            return writer.toString();
        }
        else {
            return null;
        }
    }

    public void clearBuffer(StringWriter writer) {
        if (writer != null) {
            writer.getBuffer().setLength(0);
        }
    }

    public void startRecording(StringWriter writer) {
        log.debug( "startRecording() setting writer:" + writer);
        threadWriter.set(writer);
    }

    public void stopRecording() {
        threadWriter.set(null);
    }
}
